/**
 * @purpose 嵌套集合树导入服务的JExcel实现
 * @author daizs
 * @created Mar 2, 2010
 */
package platform.common.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

import org.apache.log4j.Logger;

import platform.common.bo.AbstractNestedSetTreeNode;
import platform.common.exception.BusinessException;
import platform.common.service.ImportException;


import platform.common.service.impl.BaseLRTreeImportServiceImpl;

public abstract class BaseLRTreeImportJExcelServiceImpl extends BaseLRTreeImportServiceImpl {

    /**
	 * log4j进行日志记录。
	 */
	private Logger log = Logger.getLogger(BaseLRTreeImportServiceImpl.class);

	/**
     * @see platform.common.service.ILRTreeImportService#startImport(File,int,int,String)
     */
	public void startImport(File sourcefile,int startRow,int initValue,String isolatedFlag,int startLevel) throws BusinessException {
		
		Sheet sheet=null;
		InputStream is=null;
		jxl.Workbook rwb;
		try {
			is = new FileInputStream(sourcefile);
			rwb = Workbook.getWorkbook(is);
		} catch (Exception e) {
			closeInputStream(is);
			throw new ImportException(e);
		}
		sheet=rwb.getSheet(0);
		try {
			execImport(startRow, sheet,initValue,isolatedFlag,startLevel);
		} catch (Exception e) {
			throw  handleBusinessServiceException(e);
		}
		closeInputStream(is);
	}


	/**
     * 关闭导入文件流
     */
	private void closeInputStream(InputStream is)  {
		if(is!=null){
			try {
				is.close();
			} catch (IOException e) {
				log.error("关闭文件流出现异常", e);
			}
		}
	}

	/**
     * 执行导入.先读入startRow行数据，压入到栈的最低端。<br>
     * 然后逐行读入数据，并与栈顶数据比较，如果是栈顶数据的子节点，则继续压入栈；<br>
     * 否则则弹出栈顶数据数据，直到栈顶数据是当前文件行数据的父节点。
     * @param startRow 从文件的第几行开始导入
	 * @param sheet excel文件的sheet
	 * @param initValue 左右值的初始值，表示导入的节点数据放在那个节点下，如果为1，表示为根节点
	 * @param isolatedFlag 树节点的隔离标识
	 * @param startLevel  初始层级
	 * @throws BusinessException
     */
	private void execImport(int startRow, Sheet sheet,int initValue,String isolatedFlag,int startLevel)
			throws BusinessException {
		String errStr = "";
		try {
			int count=initValue;
			Stack nodeStack=new Stack();
			//先保存一个根节点
			Cell[] cellsInStartRow = sheet.getRow(startRow);

			Map mapaa = new HashMap();
			int dataRows=sheet.getRows();
			log.debug("excel中共有"+dataRows+"行数据");

			//开始遍历
			for(int k=startRow;k<startRow+sheet.getRows();k++){
				Cell[] cellsInRow = sheet.getRow(k);
				AbstractNestedSetTreeNode treeNode=(AbstractNestedSetTreeNode)createTreeNodeByExcelRow(cellsInRow);
				AbstractNestedSetTreeNode treeNodeInStackTop=null;
				if(!nodeStack.empty()){
					treeNodeInStackTop=(AbstractNestedSetTreeNode)nodeStack.peek();
				}else{
					//pathName记录全路径
					this.pathName = treeNode.getName();
					mapaa.put(pathName, pathName);
					treeNode.setLeftValue(count);
					nodeStack.push(treeNode);
					count++;
					continue;
				}
				//如果是子节点
				int nodeRelation=judgeNodeRelation(treeNode,treeNodeInStackTop);
				if(nodeRelation!=NODE_CHILD){//弹出栈里的节点
					count=popNodeAndStoreUtilParent(nodeStack,count,isolatedFlag,treeNode,startLevel);
				}
				//pathName记录全路径
				this.pathName += "||"+treeNode.getName();
				System.out.println(pathName);
				if(mapaa.containsKey(pathName)){
					if(errStr.equals("")){
						errStr = "第"+(k+1)+"行名称已经存在!";
					}else{
						errStr += ";第"+(k+1)+"行名称已经存在!";
					}
				}
				mapaa.put(pathName, pathName);
				treeNode.setLeftValue(count);
				nodeStack.push(treeNode);
				count++;
			}
			if(!errStr.equals("")){
				throw new BusinessException(errStr);
			}

			while(!nodeStack.empty()){//将栈里余下的数据全部写到数据库
				AbstractNestedSetTreeNode nodeInStackTop=(AbstractNestedSetTreeNode)nodeStack.pop();
				int nodeLevel=nodeStack.size();
				nodeInStackTop.setRightValue(count);
				nodeInStackTop.setTreeLevel(nodeLevel+startLevel);
				nodeInStackTop.setIsolatedFlag(isolatedFlag);
				count++;
				//保存到数据库
				nodeInStackTop.insertTreeNodeNotSetLR(domainProviderSet);
			}
		} catch (Exception e) {
			throw  handleBusinessServiceException(e);
		}
        

	}

	protected abstract AbstractNestedSetTreeNode createTreeNodeByExcelRow(Cell[] row)throws BusinessException;

}
